package net.alegen.tracker;

import java.io.File;
import java.io.FileWriter;
import java.util.ArrayList;
import java.util.List;

import org.jdom2.Document;
import org.jdom2.Element;
import org.jdom2.input.SAXBuilder;
import org.jdom2.output.Format;
import org.jdom2.output.XMLOutputter;

import android.content.Context;
import android.content.Intent;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.Bundle;
import android.os.Environment;
import android.provider.Settings;
import android.view.Menu;
import android.view.MenuItem;

import com.google.android.maps.GeoPoint;
import com.google.android.maps.MapActivity;
import com.google.android.maps.MapView;
import com.google.android.maps.MyLocationOverlay;

public class TrackerMapActivity
	extends MapActivity 
	implements LocationListener {
	
	private static final int START_GPS_REQUEST_CODE 	= 1;
	private static final int STOP_GPS_REQUEST_CODE 		= 2;
	private static final int TAKE_PICTURE_REQUEST_CODE 	= 3;
	
	private MapView mapView;
	private MyLocationOverlay myLocationOverlay;
	private LocationManager locationManager;
	private PathOverlay pathOverlay;
	
	private List<GeoPoint> pathPoints;
	private boolean isRecording;
	
	// ******************************************************************************
	// Activity methods
	// ******************************************************************************
	
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        
        this.locationManager = (LocationManager)this.getSystemService(Context.LOCATION_SERVICE);
        
        this.mapView = (MapView)this.findViewById(R.id.mapView);
        this.mapView.setBuiltInZoomControls(true);
        
        this.myLocationOverlay = new MyLocationOverlay(this, this.mapView);
        if(this.locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER))
        	this.enableMyLocationOverlay();
        
        this.pathPoints = new ArrayList<GeoPoint>();
        this.isRecording = false;
        
        this.pathOverlay = new PathOverlay(this.pathPoints);
        this.mapView.getOverlays().add(this.pathOverlay);
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.activity_main, menu);
        return true;
    }
    
    @Override
    public boolean onPrepareOptionsMenu(Menu menu) {
    	MenuItem toggleRecording = menu.findItem(R.id.toggleRecording);
    	MenuItem toggleGPS = menu.findItem(R.id.toggleGPS);
    	MenuItem takePicture = menu.findItem(R.id.takePicture);
    	if(this.isRecording)
    		toggleRecording.setTitle("Stop Recording");
    	else
    		toggleRecording.setTitle("Start Recording");
    	if(this.locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER))
    		toggleGPS.setTitle("Stop GPS");
    	else
    		toggleGPS.setTitle("Start GPS");
    	if(this.isRecording)
    		takePicture.setEnabled(true);
    	else
    		takePicture.setEnabled(false);
    	return true;
    }
    
    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
    	Intent intent;
        switch (item.getItemId()) {
        
        case R.id.toggleGPS:
        	intent = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS);
        	int requestCode;
        	if(item.getTitle().equals("Start GPS"))
        		requestCode = START_GPS_REQUEST_CODE;
        	else
        		requestCode = STOP_GPS_REQUEST_CODE;
        	this.startActivityForResult(intent, requestCode);
        	break;
        	
        case R.id.toggleRecording:
        	this.isRecording = !this.isRecording;
        	if(this.isRecording)
        		this.locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER,
        				10 * 1000,
        				0,
        				this);
        	else
        		this.locationManager.removeUpdates(this);
        	break;
        	
        case R.id.takePicture:
        	intent = new Intent(this, CameraActivity.class);
        	this.startActivityForResult(intent, TAKE_PICTURE_REQUEST_CODE);
        	break;
        	
        case R.id.save:
        	this.saveCoordinates();
        	break;
        	
        case R.id.load:
        	this.loadCoordinates();
        	break;
        }
        return false;
    }
    
    @Override
    public void onActivityResult (int requestCode, int resultCode, Intent data) {
    	super.onActivityResult(requestCode, resultCode, data);
    	if(requestCode == START_GPS_REQUEST_CODE)
    		this.enableMyLocationOverlay();
    	else if(requestCode == STOP_GPS_REQUEST_CODE)
    		this.disableMyLocationOverlay();
    }
    
	// ******************************************************************************
	// MapActivity methods
	// ******************************************************************************

	@Override
	protected boolean isRouteDisplayed() {
		return false;
	}
	
	// ******************************************************************************
	// LocationListener methods
	// ******************************************************************************
	
	public void onLocationChanged(Location location) {
		double geoConversion = 1e6;
		GeoPoint gPoint = new GeoPoint((int)(location.getLatitude() * geoConversion),
				(int)(location.getLongitude() * geoConversion));
		synchronized (this.pathPoints) {
			this.pathPoints.add(gPoint);
		}
		this.mapView.getController().animateTo(gPoint);
		this.mapView.postInvalidate();
	}

	public void onProviderDisabled(String provider) {
		this.disableMyLocationOverlay();
	}

	public void onProviderEnabled(String provider) {
		this.enableMyLocationOverlay();
	}

	public void onStatusChanged(String provider, int status, Bundle extras) { }
	
	// ******************************************************************************
	// My own methods
	// ******************************************************************************
	
	private void enableMyLocationOverlay() {
		if(!this.myLocationOverlay.isCompassEnabled())
			this.myLocationOverlay.enableCompass();
        if(!this.myLocationOverlay.isMyLocationEnabled())
        	this.myLocationOverlay.enableMyLocation();
        if(!this.mapView.getOverlays().contains(this.myLocationOverlay))
        	this.mapView.getOverlays().add(this.myLocationOverlay);
	}
	
	private void disableMyLocationOverlay() {
		if(this.myLocationOverlay.isCompassEnabled())
        	this.myLocationOverlay.disableCompass();
        if(this.myLocationOverlay.isMyLocationEnabled())
        	this.myLocationOverlay.disableMyLocation();
        if(this.mapView.getOverlays().contains(this.myLocationOverlay))
        	this.mapView.getOverlays().remove(this.myLocationOverlay);
	}
	
	private void loadCoordinates() {
		try {
			File directory = new File(new java.net.URI("file://" + Environment.getExternalStorageDirectory().getAbsolutePath() + "/Tracker"));
			if(directory.exists()) {
				
				Element rootNode = new SAXBuilder()
					.build(new File(directory.getAbsolutePath() + "/path.xml"))
					.getRootElement();
				
				List<Element> coordinates = rootNode.getChildren();
				synchronized(this.pathPoints) {
					for(Element coordinate : coordinates) {
						Element latitude = coordinate.getChild("latitude");
						Element longitude = coordinate.getChild("longitude");
						this.pathPoints.add(new GeoPoint(Integer.parseInt(latitude.getText()),
								Integer.parseInt(longitude.getText())));
					}
				}
			}
		} catch (Exception e) {
			e.printStackTrace();
		}	
	}
	
	private void saveCoordinates() {
		Element elemCoordinates = new Element("coordinates");
		Document doc = new Document(elemCoordinates);
		
		synchronized (this.pathPoints) {
			for(GeoPoint gp : this.pathPoints) {
				Element latitude = new Element("latitude");
				Element longitude = new Element("longitude");
				latitude.addContent(String.valueOf(gp.getLatitudeE6()));
				longitude.addContent(String.valueOf(gp.getLongitudeE6()));				
				
				Element elemCoordinate = new Element("coordinate");
				elemCoordinate.addContent(latitude);
				elemCoordinate.addContent(longitude);
				doc.getRootElement().addContent(elemCoordinate);
			}
		}
		
		File directory;
		try {
			directory = new File(new java.net.URI("file://" + Environment.getExternalStorageDirectory().getAbsolutePath() + "/Tracker"));
			if(!directory.exists())
				directory.mkdir();
			XMLOutputter xmlOutput = new XMLOutputter();
			xmlOutput.setFormat(Format.getPrettyFormat());
			xmlOutput.output(doc, new FileWriter(directory.getAbsolutePath() + "/path.xml"));
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}